package com.tjs.lucky.application.mq;

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.tjs.lucky.application.process.OpenAwardProcess;
import com.tjs.lucky.common.AwardState;
import com.tjs.lucky.common.GrantState;
import com.tjs.lucky.common.MQState;
import com.tjs.lucky.domain.activity.model.vo.DisAwardInvoiceVO;
import com.tjs.lucky.domain.activity.repository.IUserTakeActivityRepository;
import com.tjs.lucky.domain.activity.service.partake.IActivityPartake;
import com.tjs.lucky.domain.award.model.vo.DistributionRes;
import com.tjs.lucky.domain.award.model.vo.GoodsReq;
import com.tjs.lucky.domain.award.service.factory.DistributionGoodsFactory;
import com.tjs.lucky.domain.award.service.goods.IDistributionGoods;
import com.tjs.lucky.infrastructure.utils.EmailUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Optional;

import static com.tjs.lucky.common.Constants.*;

/**
 * @Author: 田佳澍
 * @Description: TODO：消息发送对可靠性，发送失败的处理。消费失败的处理？
 * @DateTime: 2023/6/10 15:21
 **/
@Component
public class LuckyInvoiceListener {

    private final Logger logger = LoggerFactory.getLogger(LuckyInvoiceListener.class);

    @Resource
    private DistributionGoodsFactory distributionGoodsFactory;

    @Resource
    private EmailUtil emailUtil;

    @Resource
    private IActivityPartake activityPartake;

    @RabbitListener(queues = DIS_AWARD_QUEUE_NAME)
    public void onMessageToDisAward(String msg) {
        Optional<String> message = Optional.ofNullable(msg);

        // 判断消息是否存在
        if (!message.isPresent()) {
            return;
        }

        // 处理 MQ 消息
        try {
            //  转化对象（或者你也可以重写Serializer<T>）
            DisAwardInvoiceVO disAwardInvoiceVO = JSON.parseObject(message.get(), DisAwardInvoiceVO.class);

            //  获取发送奖品工厂，执行发奖
            IDistributionGoods distributionGoodsService = distributionGoodsFactory.getDistributionGoodsService(disAwardInvoiceVO.getAwardType());
            GoodsReq goodsReq = new GoodsReq(disAwardInvoiceVO.getUId(), disAwardInvoiceVO.getOrderId(), disAwardInvoiceVO.getAwardId(), disAwardInvoiceVO.getAwardName(), disAwardInvoiceVO.getAwardContent());
            DistributionRes distributionRes = distributionGoodsService.doDistribution(goodsReq);

            Assert.isTrue(AwardState.SUCCESS.getCode().equals(distributionRes.getCode()), distributionRes.getInfo());
            // 4.1 MQ 消息消费完成，更新数据库表 user_strategy_export.grant_state = 1
            activityPartake.updateGrantState(disAwardInvoiceVO.getUId(), disAwardInvoiceVO.getOrderId(), GrantState.COMPLETE.getCode());

            //  打印日志
            logger.info("消费MQ消息，完成 queue：{} bizId：{} 发奖结果：{}", DIS_AWARD_QUEUE_NAME, disAwardInvoiceVO.getUId(), JSON.toJSONString(distributionRes));
        } catch (Exception e) {
            // 发奖环节失败，消息重试。所有到环节，发货、更新库，都需要保证幂等。
            logger.error("消费MQ消息，失败 queue：{} message：{}", DIS_AWARD_QUEUE_NAME, message.get());
            throw e;
        }
    }

    /**
     * 死信交换机...
     *
     * @param msg
     */
    @RabbitListener(queues = DL_QUEUE_NAME)
    public void listenDlQueue(String msg) {
        DisAwardInvoiceVO disAwardInvoiceVO = JSON.parseObject(msg, DisAwardInvoiceVO.class);
        activityPartake.updateInvoiceMqState(disAwardInvoiceVO.getUId(), disAwardInvoiceVO.getOrderId(), MQState.CONSUM_FAIL.getCode());
        //消息通知人工处理。
        emailUtil.sendmail("928301810@qq.com","发奖失败",disAwardInvoiceVO.toString());
        logger.info("接收到 dl.ttl.queue的消费失败消息：{}", msg);
    }

}
